home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power DOS 1996 July
/
Power DOS - July 1996.iso
/
sound
/
c_labs
/
devinfo
/
mpu401.exe
/
MIDIUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-18
|
11KB
|
344 lines
/* -------------------------------------------------------------------------- */
/* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY */
/* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE */
/* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR */
/* PURPOSE. */
/* */
/* You have a royalty-free right to use, modify, reproduce and */
/* distribute the Sample Files (and/or any modified version) in */
/* any way you find useful, provided that you agree that */
/* Creative has no warranty obligations or liability for any Sample Files. */
/*----------------------------------------------------------------------------*/
/* ---------------------------------------------------------------------------
Program: Sound Blaster 16 MIDI Utilities
Filename: MIDIUTIL.C
Author: Scott E. Sindorf
Language: Borland C
Date: 30 Jun 93
Copyright (c) 1993-1996 Creative Labs, Inc.
-----------------------------------------------------------------------------*/
#include <conio.h>
#include "midiutil.h"
#include "sbcutils.h"
extern BLASTREC blastInfo;
int MIDIType = MPU401; // MIDI type to use flag
/************************************************************************
* WRITE_MPU401_CMD: sends a command to the MPU401 port.
*
* Input: command - command byte
*
* Output: none
************************************************************************/
void Write_MPU401_Cmd(unsigned char command)
{
// check write status
while((inp(blastInfo.midiPort + 1) & MPU401_OK2WR));
outp(blastInfo.midiPort + 1, command);
}
/************************************************************************
* WRITE_MPU401_DATA: sends a data byte to the MPU401 port.
*
* Input: data - data byte
*
* Output: none
************************************************************************/
void Write_MPU401_Data(unsigned char data)
{
// check write status
while((inp(blastInfo.midiPort + 1) & MPU401_OK2WR));
outp(blastInfo.midiPort, data);
}
/************************************************************************
* WRITE_SBMIDI_DATA: sends a byte to the Sound Blaster MIDI port.
*
* Input: data - data byte
*
* Output: none
************************************************************************/
void Write_SBMIDI_Data(unsigned char data)
{
// wait for write buffer ready
while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
// send MIDI write command
outp(blastInfo.baseAddr + DSP_WR, MIDI_OUT_P);
// wait for write buffer ready
while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
// send MIDI data byte
outp(blastInfo.baseAddr + DSP_WR, data);
}
/************************************************************************
* READ_MPU401_DATA: reads a byte from the MPU401 port.
*
* Input: none
*
* Output: data byte
************************************************************************/
unsigned char Read_MPU401_Data(void)
{
// check read status
while((inp(blastInfo.midiPort + 1) & MPU401_OK2RD));
return(inp(blastInfo.midiPort));
}
/************************************************************************
* READ_SBMIDI_DATA: reads a byte from the Sound Blaster MIDI port.
*
* Input: none
*
* Output: data - data byte
************************************************************************/
unsigned char Read_SBMIDI_Data(void)
{
unsigned char data;
// wait for write buffer ready
while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
// send MIDI read command
outp(blastInfo.baseAddr + DSP_WR, MIDI_IN_P);
// wait for read buffer ready
while(!(inp(blastInfo.baseAddr + DSP_RD_ST) & MSB));
// read MIDI data byte
data = inp(blastInfo.baseAddr + DSP_RD);
// wait for write buffer ready
while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
// stop MIDI read
outp(blastInfo.baseAddr + DSP_WR, MIDI_IN_P);
return(data);
}
/************************************************************************
* SEND_MIDI_MESSAGE: Sends a MIDI message to port
*
* Input: message - MIDI message to send
* size - length of message
*
* Output: none
************************************************************************/
void Send_MIDI_Message(char far *message, int size)
{
int i;
if(MIDIType == MPU401)
for(i = 0; i < size; i++)
Write_MPU401_Data(message[i]);
else
for(i = 0; i < size; i++)
Write_SBMIDI_Data(message[i]);
}
/************************************************************************
* SET_MIDI_VOL: Sets the global volume on the requested channel
*
* Input: channel - set volume on this channel (1 to 16)
* volume - set channel to this volume (0 to 127)
*
* Output: none
*
* note: if inputs are out of range then no action occurs
************************************************************************/
void Set_MIDI_Vol(char channel, char volume)
{
char message[3];
if((channel <= 16) && (channel > 0))
if(volume >= 0)
{
message[0] = 0xb0 + channel - 1; // set channel
message[1] = 7; // set global volume command
message[2] = volume; // set volume level
Send_MIDI_Message(message, 3);
}
}
/************************************************************************
* SET_MIDI_NOTES_OFF: Turns off all notes on the given channel
*
* Input: channel - turns off all notes on this channel (1 to 16)
*
* Output: none
*
* note: if channel is out of range then no action occurs
************************************************************************/
void Set_MIDI_Notes_Off(char channel)
{
char message[3];
if((channel <= 16) && (channel > 0))
{
message[0] = 0xb0 + channel - 1; // set channel
message[1] = 0x7b; // clear all notes command
message[2] = 0;
Send_MIDI_Message(message, 3);
}
}
/************************************************************************
* SET_MIDI_PITCH_BEND: Sets pitch bend (0 = OFF).
*
* Input: channel - sets pitch bend on this channel (1 to 16)
* bend - pitch bend value (-8192 to 8191)
*
* Output: none
*
* note: if inputs are out of range then no action occurs
************************************************************************/
void Set_MIDI_Pitch_Bend(char channel, int range)
{
char message[3];
if((channel <= 16) && (channel > 0))
if((range >= -8192) && (range < 8192))
{
range += 8192;
message[0] = 0xe0 + channel - 1; // set channel
message[1] = range >> 7; // set pitch bend (MSB)
message[2] = range & 0x7f; // set pitch bend (LSB)
Send_MIDI_Message(message, 3);
}
}
/************************************************************************
* RESET_MPU401: resets the MPU401 port.
*
* Input: none
*
* Output: result - (0 = OK, -1 = ERROR)
*
* note: Error will occur if UART mode is not turned off first.
************************************************************************/
int Reset_MPU401(void)
{
int i = 100;
Write_MPU401_Cmd(MPU401_RESET); // send reset command
while((i > 0) && (Read_MPU401_Data() != MPU401_CMDOK))
i--; // offer timeout instead of lockup
if(i == 0)
return(ERROR);
else
return(OK);
}
/************************************************************************
* SET_UART_MODE: puts the MPU401 port in UART mode.
*
* Input: state - ON or OFF (Reset will return error if UART mode is on
* when reset occurs)
*
* Output: result - (0 = OK, -1 = ERROR)
************************************************************************/
int Set_UART_Mode(int state)
{
int i = 100;
if(state == ON)
{
Write_MPU401_Cmd(MPU401_UART); // turn on UART mode
while((i > 0) && (Read_MPU401_Data() != MPU401_CMDOK))
i--; // offer timeout instead of lockup
}
else
Write_MPU401_Cmd(MPU401_RESET); // turn off UART mode
if(i == 0)
return(ERROR);
else
return(OK);
}
/************************************************************************
* DETECT_MIDI: Detects the presence of the MPU-401 port or the SBMIDI
* port.
*
* Input: none
*
* Output: result - (0 = OK if found, -1 = ERROR if not found)
************************************************************************/
int Detect_MIDI(void)
{
unsigned char status;
int result = ERROR;
if(MIDIType == MPU401)
{
// check write status
status = inp(blastInfo.midiPort + 1);
if(!(status & MPU401_OK2WR))
{
Set_UART_Mode(OFF); // just in case it was left on
result = Reset_MPU401(); // does reset work?
}
}
else
result = DSPReset(); // reset the DSP
return(result);
}
/************************************************************************
* INIT_MIDI: Initializes the MIDI port. If MPU-401 port then reset
* the port and select UART mode. For either MPU-401 or
* SBMIDI ports set all master volumes to 100, turn off all
* notes, and reset all pitch bends.
*
* Input: none
*
* Output: result - (0 = OK, -1 = ERROR)
************************************************************************/
int Init_MIDI(void)
{
int i;
if(MIDIType == MPU401)
{
if(Reset_MPU401() == ERROR) // reset port
return(ERROR);
if(Set_UART_Mode(ON) == ERROR) // set UART mode
return(ERROR);
}
for(i = 1; i <= 16; i++)
{
Set_MIDI_Vol(i, 100); // set channel volume
Set_MIDI_Notes_Off(i); // turn off all notes
Set_MIDI_Pitch_Bend(i, 0); // reset pitch bends
}
return(OK);
}
/************************************************************************
* EXIT_MIDI: Terminates MIDI driver by turning off all notes (and
* turning off UART mode if using MPU-401 port).
*
* Input: none
*
* Output: none
************************************************************************/
void Exit_MIDI(void)
{
int i;
for(i = 0; i < 16; i++)
Set_MIDI_Notes_Off(i); // turn off all notes
if(MIDIType == MPU401)
Set_UART_Mode(OFF); // exit UART mode
}